﻿using System.Diagnostics;

namespace DimensionsHelper.LanguageService.Syntax;

public class FileInclude : SourceNode
{
    private readonly SourceNode _includeKeywordToken;
    private SourceNode _includeFileName;

    internal FileInclude(SourceNode includeKeywordToken, SourceNode? includeFileName,
        SourceNode? parent) :
        base(parent, SyntaxKinds.FileInclude)
    {
        SetChildField(ref _includeKeywordToken, includeKeywordToken);
        if (includeFileName != null)
        {
            SetChildField(ref _includeFileName, includeFileName);
        }
        else
        {
            _includeFileName = Default;
        }

        if (includeKeywordToken.HasPrecedingLinebreak)
        {
            SetFlags(SyntaxNodeFlags.PrecedingLinebreak);
        }

        ResolvedFilePath = string.Empty;
    }


    /// <summary>
    ///     #include 关键字
    /// </summary>
    public SourceNode IncludeKeywordToken => _includeKeywordToken;


    /// <summary>
    ///     如果引用文件路径的节点列表是空，此属性为<see langword="true" />。
    /// </summary>
    public bool IsPathMissing => IsNullOrDefault(IncludeFileName);


    /// <summary>
    ///     引用文件路径的表达式，可能是通过宏扩展得到的。
    /// </summary>
    public SourceNode IncludeFileName => _includeFileName;


    /// <summary>
    ///     和根目录合并后的完整路径。
    /// </summary>
    public string ResolvedFilePath { get; internal set; }


    /// <summary>
    ///     引用路径指向的源文件，如果指定路径不存在或者读取文件失败，此属性将为<see langword="null" />。
    /// </summary>
    public SourceTextFile? Source { get; private set; }


    /// <summary>
    ///     更新引用的源文件
    /// </summary>
    public FileInclude Update(SourceTextFile? source)
    {
        Source = source;
        return this;
    }


    /// <summary>
    ///     更新应用文件路径节点
    /// </summary>
    public FileInclude Update(PreExpression includeFileName)
    {
        SetChildField(ref _includeFileName, IsNullOrDefault, includeFileName);
        return this;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        if (!IsPathMissing)
        {
            Accept(visitor, IncludeFileName);
        }
    }
}


public static partial class NodeFactory
{
    public static FileInclude CreateFileInclude(SourceNode? parent, SourceNode includeKeywordToken,
        SourceNode? includeFileName)
    {
        Debug.Assert(includeKeywordToken.IsNode(SyntaxKinds.PreIncludeKeywordToken));
        return new FileInclude(includeKeywordToken, includeFileName, parent);
    }
}